Date: Thu, 1 Oct 2009 06:45:58 GMT From: Kazumi MORINAGA <morinaga@riken.jp> To: freebsd-gnats-submit@FreeBSD.org Subject: amd64/139271: [PATCH] hpacucli does not work on the amd64 kernel Message-ID: <200910010645.n916jwlG072271@www.freebsd.org> Resent-Message-ID: <200910010650.n916o1uH039043@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 139271 >Category: amd64 >Synopsis: [PATCH] hpacucli does not work on the amd64 kernel >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-amd64 >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Thu Oct 01 06:50:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Kazumi MORINAGA >Release: amd64 FreeBSD 7.2-RELEASE, amd64 FreeBSD 8.0 beta3 >Organization: RIKEN, Japan >Environment: FreeBSD test 7.2-RELEASE FreeBSD 7.2-RELEASE #0: Fri Sep 18 20:35:39 JST 2009 root@test:/usr/obj/usr/src/sys/GENERIC amd64 (patched GENERIC kernel) >Description: The hpacucli (ports/sysutils/hpacucli) that is an utility for the HP Smart Array RAID controller could not detect controller cards on the amd64 kernel. I tested the patch for pci_users.c that was posted to the freebsd-proliant@freebsd.org by Mr. John Hay on March 30, 2009. - http://lists.freebsd.org/pipermail/freebsd-proliant/2009-March/000498.html - Subject: hpacucli on 7-stable amd64, some progress The environment of the test is as follows, - HP DL360G5 with Smart Array P400i. - Patched GENERIC kernel amd64 ( FreeBSD 7.2-RELEASE / FreeBSD 8.0 beta3 ) It seems to work correctly in some commands (show, modify cacheratio=...., array all show, logcaldrive show, physicaldrive show). --- show all information ctrl all show Controller Smart Array P400i at 0 Bus Interface: PCI Slot: 0 Serial Number: PH91MQ2642 Cache serialnumber: PA82C0J9SX32IG RAID 6 (ADG) Status: Enabled RAID 6 (ADG) Enabler Status: Enabled Controller Status: OK Chassis Slot: 1 Hardware Revision: Rev E Firmware Version: 5.26 Rebuild Priority: Medium Expand Priority: Medium Surface Scan Delay: 15 sec Cache Board Present: True Cache Status: OK Accelerator Ratio: 100/0 (read/write) Total Cache Size: 256 MB Battery Pack Count: 1 Battery Status: OK --- modify cacheratio controller slot=0 modify cacheratio=25/75 controller slot=0 show ...  Cache Status: OK  Accelerator Ratio: 25/75 (read/write) ... ctrl slot=0 modify cacheratio=100/0 ctrl slot=0 show ...  Cache Status: OK  Accelerator Ratio: 100/0 (read/write) ... --- show array information ctrl slot=0 array all show  Smart Array P400i in Slot 0   Array: A   Interface Type: SAS   Unused Space: 0 MB   Status: OK --- show logcaldrive information ctrl slot=0 logcaldrive all show  Smart Array P400i in Slot 0   Logical Drive: 1   Size: 68.3 GB   Fault Tolerance: 1+0   Heads: 255   Sectors Per Track: 32   Cylinders: 17562   Stripe Size: 128 KB   Status: Ok   Array Accelerator: Enabled   Has Data On Drive: True   Unique Identifier: xxxx (masked)   Preferred Controller Chassis Slot: 1 --- show physicaldrive information ctrl slot=0 physicaldrive all show  Smart Array P400i in Slot 0  physicaldrive 1:1   Port: 1I   Box: 1   Bay: 1   Status: OK   Drive Type: Data Drive   Interface Type: SAS   Size: 73.4 GB   Transfer Speed: 3.0 Gbps   Rotational Speed: 15000   Firmware Revision: HPD3   Serial Number: xxxx (masked)  physicaldrive 1:2   Port: 1I   Box: 1   Bay: 2   Status: OK   Drive Type: Data Drive   Interface Type: SAS   Size: 73.4 GB   Transfer Speed: 3.0 Gbps   Rotational Speed: 15000   Firmware Revision: HPD3   Serial Number: xxxx (masked) >How-To-Repeat: Install the hpacucli from ports (required: modification of the makefile). Run the hpacucli with "ctrl all show" option. It will display the following message. Error: No controllers detected. >Fix: Patch to /usr/src/sys/dev/pci/pci_user.c. This patch is same as Mr. Jhon Hay's patch that was posted to the freebsd-proliant@freebsd.org by Mr. John Hay on March 30, 2009. - http://lists.freebsd.org/pipermail/freebsd-proliant/2009-March/000498.html - Subject: hpacucli on 7-stable amd64, some progress Patch attached with submission follows: --- pci_user.c.orig 2009-09-10 11:36:37.000000000 +0900 +++ pci_user.c 2009-09-10 11:36:41.000000000 +0900 @@ -225,6 +225,49 @@ u_int32_t pi_data; /* data to write or result of read */ }; +#ifdef COMPAT_IA32 +struct pci_conf_old32 { + struct pcisel_old pc_sel; /* bus+slot+function */ + u_int8_t pc_hdr; /* PCI header type */ + u_int16_t pc_subvendor; /* card vendor ID */ + u_int16_t pc_subdevice; /* card device ID, assigned by + card vendor */ + u_int16_t pc_vendor; /* chip vendor ID */ + u_int16_t pc_device; /* chip device ID, assigned by + chip vendor */ + u_int8_t pc_class; /* chip PCI class */ + u_int8_t pc_subclass; /* chip PCI subclass */ + u_int8_t pc_progif; /* chip PCI programming interface */ + u_int8_t pc_revid; /* chip revision ID */ + char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ + u_int32_t pd_unit; /* device unit number (u_long) */ +}; + +struct pci_match_conf_old32 { + struct pcisel_old pc_sel; /* bus+slot+function */ + char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ + u_int32_t pd_unit; /* Unit number (u_long) */ + u_int16_t pc_vendor; /* PCI Vendor ID */ + u_int16_t pc_device; /* PCI Device ID */ + u_int8_t pc_class; /* PCI class */ + pci_getconf_flags_old flags; /* Matching expression */ +}; + +struct pci_conf_io32 { + u_int32_t pat_buf_len; /* pattern buffer length */ + u_int32_t num_patterns; /* number of patterns */ + u_int32_t patterns; /* pattern buffer (struct pci_match_conf_old32 *) */ + u_int32_t match_buf_len; /* match buffer length */ + u_int32_t num_matches; /* number of matches returned */ + u_int32_t matches; /* match buffer (struct pci_conf_old32 *) */ + u_int32_t offset; /* offset into device list */ + u_int32_t generation; /* device list generation */ + pci_getconf_status status; /* request status */ +}; + +#define PCIOCGETCONF_OLD32 _IOWR('p', 1, struct pci_conf_io32) +#endif + #define PCIOCGETCONF_OLD _IOWR('p', 1, struct pci_conf_io) #define PCIOCREAD_OLD _IOWR('p', 2, struct pci_io_old) #define PCIOCWRITE_OLD _IOWR('p', 3, struct pci_io_old) @@ -295,6 +338,69 @@ return(1); } +static int +pci_conf_match_old32(struct pci_match_conf_old32 *matches, int num_matches, + struct pci_conf *match_buf) +{ + int i; + + if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0)) + return(1); + + for (i = 0; i < num_matches; i++) { + if (match_buf->pc_sel.pc_domain != 0) + continue; + + /* + * I'm not sure why someone would do this...but... + */ + if (matches[i].flags == PCI_GETCONF_NO_MATCH_OLD) + continue; + + /* + * Look at each of the match flags. If it's set, do the + * comparison. If the comparison fails, we don't have a + * match, go on to the next item if there is one. + */ + if (((matches[i].flags & PCI_GETCONF_MATCH_BUS_OLD) != 0) + && (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_DEV_OLD) != 0) + && (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC_OLD) != 0) + && (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR_OLD) != 0) + && (match_buf->pc_vendor != matches[i].pc_vendor)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE_OLD) != 0) + && (match_buf->pc_device != matches[i].pc_device)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS_OLD) != 0) + && (match_buf->pc_class != matches[i].pc_class)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT_OLD) != 0) + && ((u_int32_t)match_buf->pd_unit != matches[i].pd_unit)) + continue; + + if (((matches[i].flags & PCI_GETCONF_MATCH_NAME_OLD) != 0) + && (strncmp(matches[i].pd_name, match_buf->pd_name, + sizeof(match_buf->pd_name)) != 0)) + continue; + + return(0); + } + + return(1); +} + #endif static int @@ -314,13 +420,21 @@ size_t confsz, iolen, pbufsz; int error, ionum, i, num_patterns; #ifdef PRE7_COMPAT +#ifdef COMPAT_IA32 + struct pci_conf_io32 *cio32; +#endif struct pci_conf_old conf_old; + struct pci_conf_old32 conf_old32; struct pci_io iodata; struct pci_io_old *io_old; struct pci_match_conf_old *pattern_buf_old; + struct pci_match_conf_old32 *pattern_buf_old32; + cio = NULL; + cio32 = NULL; io_old = NULL; pattern_buf_old = NULL; + pattern_buf_old32 = NULL; if (!(flag & FWRITE) && cmd != PCIOCGETBAR && cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD) @@ -332,11 +446,27 @@ switch(cmd) { #ifdef PRE7_COMPAT + case PCIOCGETCONF_OLD32: + cio32 = (struct pci_conf_io32 *)data; + cio = malloc(sizeof(struct pci_conf_io), M_TEMP, M_WAITOK); + cio->pat_buf_len = cio32->pat_buf_len; + cio->num_patterns = cio32->num_patterns; + cio->patterns = (void *)(uintptr_t)cio32->patterns; + cio->match_buf_len = cio32->match_buf_len; + cio->num_matches = cio32->num_matches; + cio->matches = (void *)(uintptr_t)cio32->matches; + cio->offset = cio32->offset; + cio->generation = cio32->generation; + cio->status = cio32->status; + cio32->num_matches = 0; + /* FALLTHROUGH */ + case PCIOCGETCONF_OLD: /* FALLTHROUGH */ #endif case PCIOCGETCONF: - cio = (struct pci_conf_io *)data; + if (cio == NULL) + cio = (struct pci_conf_io *)data; pattern_buf = NULL; num_patterns = 0; @@ -354,7 +484,7 @@ && (cio->generation != pci_generation)){ cio->status = PCI_GETCONF_LIST_CHANGED; error = 0; - break; + goto getconfexit; } /* @@ -364,7 +494,7 @@ if (cio->offset >= pci_numdevs) { cio->status = PCI_GETCONF_LAST_DEVICE; error = 0; - break; + goto getconfexit; } /* get the head of the device queue */ @@ -377,6 +507,11 @@ * didn't specify a multiple of that size. */ #ifdef PRE7_COMPAT +#ifdef COMPAT_IA32 + if (cmd == PCIOCGETCONF_OLD32) + confsz = sizeof(struct pci_conf_old32); + else +#endif if (cmd == PCIOCGETCONF_OLD) confsz = sizeof(struct pci_conf_old); else @@ -411,6 +546,11 @@ * updated their kernel but not their userland. */ #ifdef PRE7_COMPAT +#ifdef COMPAT_IA32 + if (cmd == PCIOCGETCONF_OLD32) + pbufsz = sizeof(struct pci_match_conf_old32); + else +#endif if (cmd == PCIOCGETCONF_OLD) pbufsz = sizeof(struct pci_match_conf_old); else @@ -420,13 +560,19 @@ /* The user made a mistake, return an error. */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; - break; + goto getconfexit; } /* * Allocate a buffer to hold the patterns. */ #ifdef PRE7_COMPAT + if (cmd == PCIOCGETCONF_OLD32) { + pattern_buf_old32 = malloc(cio->pat_buf_len, + M_TEMP, M_WAITOK); + error = copyin(cio->patterns, + pattern_buf_old32, cio->pat_buf_len); + } else if (cmd == PCIOCGETCONF_OLD) { pattern_buf_old = malloc(cio->pat_buf_len, M_TEMP, M_WAITOK); @@ -452,7 +598,7 @@ */ cio->status = PCI_GETCONF_ERROR; error = EINVAL; - break; + goto getconfexit; } /* @@ -484,7 +630,11 @@ } #ifdef PRE7_COMPAT - if ((cmd == PCIOCGETCONF_OLD && + if ((cmd == PCIOCGETCONF_OLD32 && + (pattern_buf_old32 == NULL || + pci_conf_match_old32(pattern_buf_old32, + num_patterns, &dinfo->conf) == 0)) || + (cmd == PCIOCGETCONF_OLD && (pattern_buf_old == NULL || pci_conf_match_old(pattern_buf_old, num_patterns, &dinfo->conf) == 0)) || @@ -509,6 +659,38 @@ break; #ifdef PRE7_COMPAT + if (cmd == PCIOCGETCONF_OLD32) { + conf_old32.pc_sel.pc_bus = + dinfo->conf.pc_sel.pc_bus; + conf_old32.pc_sel.pc_dev = + dinfo->conf.pc_sel.pc_dev; + conf_old32.pc_sel.pc_func = + dinfo->conf.pc_sel.pc_func; + conf_old32.pc_hdr = dinfo->conf.pc_hdr; + conf_old32.pc_subvendor = + dinfo->conf.pc_subvendor; + conf_old32.pc_subdevice = + dinfo->conf.pc_subdevice; + conf_old32.pc_vendor = + dinfo->conf.pc_vendor; + conf_old32.pc_device = + dinfo->conf.pc_device; + conf_old32.pc_class = + dinfo->conf.pc_class; + conf_old32.pc_subclass = + dinfo->conf.pc_subclass; + conf_old32.pc_progif = + dinfo->conf.pc_progif; + conf_old32.pc_revid = + dinfo->conf.pc_revid; + strncpy(conf_old32.pd_name, + dinfo->conf.pd_name, + sizeof(conf_old32.pd_name)); + conf_old32.pd_name[PCI_MAXNAMELEN] = 0; + conf_old32.pd_unit = + (u_int32_t)dinfo->conf.pd_unit; + confdata = &conf_old32; + } else if (cmd == PCIOCGETCONF_OLD) { conf_old.pc_sel.pc_bus = dinfo->conf.pc_sel.pc_bus; @@ -575,9 +757,22 @@ cio->status = PCI_GETCONF_MORE_DEVS; getconfexit: +#ifdef COMPAT_IA32 + if (cmd == PCIOCGETCONF_OLD32) { + cio32->status = cio->status; + cio32->generation = cio->generation; + cio32->offset = cio->offset; + cio32->num_matches = cio->num_matches; + if (cio != NULL) + free(cio, M_TEMP); + } +#endif + if (pattern_buf != NULL) free(pattern_buf, M_TEMP); #ifdef PRE7_COMPAT + if (pattern_buf_old32 != NULL) + free(pattern_buf_old32, M_TEMP); if (pattern_buf_old != NULL) free(pattern_buf_old, M_TEMP); #endif >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910010645.n916jwlG072271>