diff options
| author | Steve French <sfrench@us.ibm.com> | 2006-01-12 17:47:08 -0500 | 
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2006-01-12 17:47:08 -0500 | 
| commit | 94bc2be31a01a3055ec94176e595dfe208e92d3b (patch) | |
| tree | ebfbe81c6718a6390bfa1b99c6d228237d818576 /drivers/message/i2o/device.c | |
| parent | c32a0b689cb9cc160cfcd19735bbf50bb70c6ef4 (diff) | |
| parent | 58cba4650a7a414eabd2b40cc9d8e45fcdf192d9 (diff) | |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'drivers/message/i2o/device.c')
| -rw-r--r-- | drivers/message/i2o/device.c | 339 | 
1 files changed, 153 insertions, 186 deletions
| diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 8eb50cdb8ae1..ee183053fa23 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c | |||
| @@ -35,18 +35,18 @@ | |||
| 35 | static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, | 35 | static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, | 
| 36 | u32 type) | 36 | u32 type) | 
| 37 | { | 37 | { | 
| 38 | struct i2o_message __iomem *msg; | 38 | struct i2o_message *msg; | 
| 39 | u32 m; | ||
| 40 | 39 | ||
| 41 | m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); | 40 | msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); | 
| 42 | if (m == I2O_QUEUE_EMPTY) | 41 | if (IS_ERR(msg)) | 
| 43 | return -ETIMEDOUT; | 42 | return PTR_ERR(msg); | 
| 44 | 43 | ||
| 45 | writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); | 44 | msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); | 
| 46 | writel(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid, &msg->u.head[1]); | 45 | msg->u.head[1] = | 
| 47 | writel(type, &msg->body[0]); | 46 | cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid); | 
| 47 | msg->body[0] = cpu_to_le32(type); | ||
| 48 | 48 | ||
| 49 | return i2o_msg_post_wait(dev->iop, m, 60); | 49 | return i2o_msg_post_wait(dev->iop, msg, 60); | 
| 50 | } | 50 | } | 
| 51 | 51 | ||
| 52 | /** | 52 | /** | 
| @@ -123,7 +123,6 @@ int i2o_device_claim_release(struct i2o_device *dev) | |||
| 123 | return rc; | 123 | return rc; | 
| 124 | } | 124 | } | 
| 125 | 125 | ||
| 126 | |||
| 127 | /** | 126 | /** | 
| 128 | * i2o_device_release - release the memory for a I2O device | 127 | * i2o_device_release - release the memory for a I2O device | 
| 129 | * @dev: I2O device which should be released | 128 | * @dev: I2O device which should be released | 
| @@ -140,10 +139,10 @@ static void i2o_device_release(struct device *dev) | |||
| 140 | kfree(i2o_dev); | 139 | kfree(i2o_dev); | 
| 141 | } | 140 | } | 
| 142 | 141 | ||
| 143 | |||
| 144 | /** | 142 | /** | 
| 145 | * i2o_device_class_show_class_id - Displays class id of I2O device | 143 | * i2o_device_show_class_id - Displays class id of I2O device | 
| 146 | * @cd: class device of which the class id should be displayed | 144 | * @dev: device of which the class id should be displayed | 
| 145 | * @attr: pointer to device attribute | ||
| 147 | * @buf: buffer into which the class id should be printed | 146 | * @buf: buffer into which the class id should be printed | 
| 148 | * | 147 | * | 
| 149 | * Returns the number of bytes which are printed into the buffer. | 148 | * Returns the number of bytes which are printed into the buffer. | 
| @@ -159,15 +158,15 @@ static ssize_t i2o_device_show_class_id(struct device *dev, | |||
| 159 | } | 158 | } | 
| 160 | 159 | ||
| 161 | /** | 160 | /** | 
| 162 | * i2o_device_class_show_tid - Displays TID of I2O device | 161 | * i2o_device_show_tid - Displays TID of I2O device | 
| 163 | * @cd: class device of which the TID should be displayed | 162 | * @dev: device of which the TID should be displayed | 
| 164 | * @buf: buffer into which the class id should be printed | 163 | * @attr: pointer to device attribute | 
| 164 | * @buf: buffer into which the TID should be printed | ||
| 165 | * | 165 | * | 
| 166 | * Returns the number of bytes which are printed into the buffer. | 166 | * Returns the number of bytes which are printed into the buffer. | 
| 167 | */ | 167 | */ | 
| 168 | static ssize_t i2o_device_show_tid(struct device *dev, | 168 | static ssize_t i2o_device_show_tid(struct device *dev, | 
| 169 | struct device_attribute *attr, | 169 | struct device_attribute *attr, char *buf) | 
| 170 | char *buf) | ||
| 171 | { | 170 | { | 
| 172 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 171 | struct i2o_device *i2o_dev = to_i2o_device(dev); | 
| 173 | 172 | ||
| @@ -175,6 +174,7 @@ static ssize_t i2o_device_show_tid(struct device *dev, | |||
| 175 | return strlen(buf) + 1; | 174 | return strlen(buf) + 1; | 
| 176 | } | 175 | } | 
| 177 | 176 | ||
| 177 | /* I2O device attributes */ | ||
| 178 | struct device_attribute i2o_device_attrs[] = { | 178 | struct device_attribute i2o_device_attrs[] = { | 
| 179 | __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL), | 179 | __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL), | 
| 180 | __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL), | 180 | __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL), | 
| @@ -193,12 +193,10 @@ static struct i2o_device *i2o_device_alloc(void) | |||
| 193 | { | 193 | { | 
| 194 | struct i2o_device *dev; | 194 | struct i2o_device *dev; | 
| 195 | 195 | ||
| 196 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | 196 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 
| 197 | if (!dev) | 197 | if (!dev) | 
| 198 | return ERR_PTR(-ENOMEM); | 198 | return ERR_PTR(-ENOMEM); | 
| 199 | 199 | ||
| 200 | memset(dev, 0, sizeof(*dev)); | ||
| 201 | |||
| 202 | INIT_LIST_HEAD(&dev->list); | 200 | INIT_LIST_HEAD(&dev->list); | 
| 203 | init_MUTEX(&dev->lock); | 201 | init_MUTEX(&dev->lock); | 
| 204 | 202 | ||
| @@ -209,66 +207,6 @@ static struct i2o_device *i2o_device_alloc(void) | |||
| 209 | } | 207 | } | 
| 210 | 208 | ||
| 211 | /** | 209 | /** | 
| 212 | * i2o_setup_sysfs_links - Adds attributes to the I2O device | ||
| 213 | * @cd: I2O class device which is added to the I2O device class | ||
| 214 | * | ||
| 215 | * This function get called when a I2O device is added to the class. It | ||
| 216 | * creates the attributes for each device and creates user/parent symlink | ||
| 217 | * if necessary. | ||
| 218 | * | ||
| 219 | * Returns 0 on success or negative error code on failure. | ||
| 220 | */ | ||
| 221 | static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev) | ||
| 222 | { | ||
| 223 | struct i2o_controller *c = i2o_dev->iop; | ||
| 224 | struct i2o_device *tmp; | ||
| 225 | |||
| 226 | /* create user entries for this device */ | ||
| 227 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); | ||
| 228 | if (tmp && tmp != i2o_dev) | ||
| 229 | sysfs_create_link(&i2o_dev->device.kobj, | ||
| 230 | &tmp->device.kobj, "user"); | ||
| 231 | |||
| 232 | /* create user entries refering to this device */ | ||
| 233 | list_for_each_entry(tmp, &c->devices, list) | ||
| 234 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid && | ||
| 235 | tmp != i2o_dev) | ||
| 236 | sysfs_create_link(&tmp->device.kobj, | ||
| 237 | &i2o_dev->device.kobj, "user"); | ||
| 238 | |||
| 239 | /* create parent entries for this device */ | ||
| 240 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); | ||
| 241 | if (tmp && tmp != i2o_dev) | ||
| 242 | sysfs_create_link(&i2o_dev->device.kobj, | ||
| 243 | &tmp->device.kobj, "parent"); | ||
| 244 | |||
| 245 | /* create parent entries refering to this device */ | ||
| 246 | list_for_each_entry(tmp, &c->devices, list) | ||
| 247 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid && | ||
| 248 | tmp != i2o_dev) | ||
| 249 | sysfs_create_link(&tmp->device.kobj, | ||
| 250 | &i2o_dev->device.kobj, "parent"); | ||
| 251 | } | ||
| 252 | |||
| 253 | static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev) | ||
| 254 | { | ||
| 255 | struct i2o_controller *c = i2o_dev->iop; | ||
| 256 | struct i2o_device *tmp; | ||
| 257 | |||
| 258 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); | ||
| 259 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); | ||
| 260 | |||
| 261 | list_for_each_entry(tmp, &c->devices, list) { | ||
| 262 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | ||
| 263 | sysfs_remove_link(&tmp->device.kobj, "parent"); | ||
| 264 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | ||
| 265 | sysfs_remove_link(&tmp->device.kobj, "user"); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | |||
| 270 | |||
| 271 | /** | ||
| 272 | * i2o_device_add - allocate a new I2O device and add it to the IOP | 210 | * i2o_device_add - allocate a new I2O device and add it to the IOP | 
| 273 | * @iop: I2O controller where the device is on | 211 | * @iop: I2O controller where the device is on | 
| 274 | * @entry: LCT entry of the I2O device | 212 | * @entry: LCT entry of the I2O device | 
| @@ -282,33 +220,57 @@ static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev) | |||
| 282 | static struct i2o_device *i2o_device_add(struct i2o_controller *c, | 220 | static struct i2o_device *i2o_device_add(struct i2o_controller *c, | 
| 283 | i2o_lct_entry * entry) | 221 | i2o_lct_entry * entry) | 
| 284 | { | 222 | { | 
| 285 | struct i2o_device *dev; | 223 | struct i2o_device *i2o_dev, *tmp; | 
| 286 | 224 | ||
| 287 | dev = i2o_device_alloc(); | 225 | i2o_dev = i2o_device_alloc(); | 
| 288 | if (IS_ERR(dev)) { | 226 | if (IS_ERR(i2o_dev)) { | 
| 289 | printk(KERN_ERR "i2o: unable to allocate i2o device\n"); | 227 | printk(KERN_ERR "i2o: unable to allocate i2o device\n"); | 
| 290 | return dev; | 228 | return i2o_dev; | 
| 291 | } | 229 | } | 
| 292 | 230 | ||
| 293 | dev->lct_data = *entry; | 231 | i2o_dev->lct_data = *entry; | 
| 294 | dev->iop = c; | ||
| 295 | 232 | ||
| 296 | snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, | 233 | snprintf(i2o_dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, | 
| 297 | dev->lct_data.tid); | 234 | i2o_dev->lct_data.tid); | 
| 298 | 235 | ||
| 299 | dev->device.parent = &c->device; | 236 | i2o_dev->iop = c; | 
| 237 | i2o_dev->device.parent = &c->device; | ||
| 300 | 238 | ||
| 301 | device_register(&dev->device); | 239 | device_register(&i2o_dev->device); | 
| 302 | 240 | ||
| 303 | list_add_tail(&dev->list, &c->devices); | 241 | list_add_tail(&i2o_dev->list, &c->devices); | 
| 304 | 242 | ||
| 305 | i2o_setup_sysfs_links(dev); | 243 | /* create user entries for this device */ | 
| 244 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); | ||
| 245 | if (tmp && (tmp != i2o_dev)) | ||
| 246 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, | ||
| 247 | "user"); | ||
| 306 | 248 | ||
| 307 | i2o_driver_notify_device_add_all(dev); | 249 | /* create user entries refering to this device */ | 
| 250 | list_for_each_entry(tmp, &c->devices, list) | ||
| 251 | if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | ||
| 252 | && (tmp != i2o_dev)) | ||
| 253 | sysfs_create_link(&tmp->device.kobj, | ||
| 254 | &i2o_dev->device.kobj, "user"); | ||
| 308 | 255 | ||
| 309 | pr_debug("i2o: device %s added\n", dev->device.bus_id); | 256 | /* create parent entries for this device */ | 
| 257 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); | ||
| 258 | if (tmp && (tmp != i2o_dev)) | ||
| 259 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, | ||
| 260 | "parent"); | ||
| 310 | 261 | ||
| 311 | return dev; | 262 | /* create parent entries refering to this device */ | 
| 263 | list_for_each_entry(tmp, &c->devices, list) | ||
| 264 | if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | ||
| 265 | && (tmp != i2o_dev)) | ||
| 266 | sysfs_create_link(&tmp->device.kobj, | ||
| 267 | &i2o_dev->device.kobj, "parent"); | ||
| 268 | |||
| 269 | i2o_driver_notify_device_add_all(i2o_dev); | ||
| 270 | |||
| 271 | pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id); | ||
| 272 | |||
| 273 | return i2o_dev; | ||
| 312 | } | 274 | } | 
| 313 | 275 | ||
| 314 | /** | 276 | /** | 
| @@ -321,9 +283,22 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, | |||
| 321 | */ | 283 | */ | 
| 322 | void i2o_device_remove(struct i2o_device *i2o_dev) | 284 | void i2o_device_remove(struct i2o_device *i2o_dev) | 
| 323 | { | 285 | { | 
| 286 | struct i2o_device *tmp; | ||
| 287 | struct i2o_controller *c = i2o_dev->iop; | ||
| 288 | |||
| 324 | i2o_driver_notify_device_remove_all(i2o_dev); | 289 | i2o_driver_notify_device_remove_all(i2o_dev); | 
| 325 | i2o_remove_sysfs_links(i2o_dev); | 290 | |
| 291 | sysfs_remove_link(&i2o_dev->device.kobj, "parent"); | ||
| 292 | sysfs_remove_link(&i2o_dev->device.kobj, "user"); | ||
| 293 | |||
| 294 | list_for_each_entry(tmp, &c->devices, list) { | ||
| 295 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | ||
| 296 | sysfs_remove_link(&tmp->device.kobj, "parent"); | ||
| 297 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | ||
| 298 | sysfs_remove_link(&tmp->device.kobj, "user"); | ||
| 299 | } | ||
| 326 | list_del(&i2o_dev->list); | 300 | list_del(&i2o_dev->list); | 
| 301 | |||
| 327 | device_unregister(&i2o_dev->device); | 302 | device_unregister(&i2o_dev->device); | 
| 328 | } | 303 | } | 
| 329 | 304 | ||
| @@ -341,56 +316,83 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
| 341 | { | 316 | { | 
| 342 | struct i2o_device *dev, *tmp; | 317 | struct i2o_device *dev, *tmp; | 
| 343 | i2o_lct *lct; | 318 | i2o_lct *lct; | 
| 344 | int i; | 319 | u32 *dlct = c->dlct.virt; | 
| 345 | int max; | 320 | int max = 0, i = 0; | 
| 321 | u16 table_size; | ||
| 322 | u32 buf; | ||
| 346 | 323 | ||
| 347 | down(&c->lct_lock); | 324 | down(&c->lct_lock); | 
| 348 | 325 | ||
| 349 | kfree(c->lct); | 326 | kfree(c->lct); | 
| 350 | 327 | ||
| 351 | lct = c->dlct.virt; | 328 | buf = le32_to_cpu(*dlct++); | 
| 329 | table_size = buf & 0xffff; | ||
| 352 | 330 | ||
| 353 | c->lct = kmalloc(lct->table_size * 4, GFP_KERNEL); | 331 | lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); | 
| 354 | if (!c->lct) { | 332 | if (!lct) { | 
| 355 | up(&c->lct_lock); | 333 | up(&c->lct_lock); | 
| 356 | return -ENOMEM; | 334 | return -ENOMEM; | 
| 357 | } | 335 | } | 
| 358 | 336 | ||
| 359 | if (lct->table_size * 4 > c->dlct.len) { | 337 | lct->lct_ver = buf >> 28; | 
| 360 | memcpy(c->lct, c->dlct.virt, c->dlct.len); | 338 | lct->boot_tid = buf >> 16 & 0xfff; | 
| 361 | up(&c->lct_lock); | 339 | lct->table_size = table_size; | 
| 362 | return -EAGAIN; | 340 | lct->change_ind = le32_to_cpu(*dlct++); | 
| 363 | } | 341 | lct->iop_flags = le32_to_cpu(*dlct++); | 
| 364 | 342 | ||
| 365 | memcpy(c->lct, c->dlct.virt, lct->table_size * 4); | 343 | table_size -= 3; | 
| 366 | |||
| 367 | lct = c->lct; | ||
| 368 | |||
| 369 | max = (lct->table_size - 3) / 9; | ||
| 370 | 344 | ||
| 371 | pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, | 345 | pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, | 
| 372 | lct->table_size); | 346 | lct->table_size); | 
| 373 | 347 | ||
| 374 | /* remove devices, which are not in the LCT anymore */ | 348 | while (table_size > 0) { | 
| 375 | list_for_each_entry_safe(dev, tmp, &c->devices, list) { | 349 | i2o_lct_entry *entry = &lct->lct_entry[max]; | 
| 376 | int found = 0; | 350 | int found = 0; | 
| 377 | 351 | ||
| 378 | for (i = 0; i < max; i++) { | 352 | buf = le32_to_cpu(*dlct++); | 
| 379 | if (lct->lct_entry[i].tid == dev->lct_data.tid) { | 353 | entry->entry_size = buf & 0xffff; | 
| 354 | entry->tid = buf >> 16 & 0xfff; | ||
| 355 | |||
| 356 | entry->change_ind = le32_to_cpu(*dlct++); | ||
| 357 | entry->device_flags = le32_to_cpu(*dlct++); | ||
| 358 | |||
| 359 | buf = le32_to_cpu(*dlct++); | ||
| 360 | entry->class_id = buf & 0xfff; | ||
| 361 | entry->version = buf >> 12 & 0xf; | ||
| 362 | entry->vendor_id = buf >> 16; | ||
| 363 | |||
| 364 | entry->sub_class = le32_to_cpu(*dlct++); | ||
| 365 | |||
| 366 | buf = le32_to_cpu(*dlct++); | ||
| 367 | entry->user_tid = buf & 0xfff; | ||
| 368 | entry->parent_tid = buf >> 12 & 0xfff; | ||
| 369 | entry->bios_info = buf >> 24; | ||
| 370 | |||
| 371 | memcpy(&entry->identity_tag, dlct, 8); | ||
| 372 | dlct += 2; | ||
| 373 | |||
| 374 | entry->event_capabilities = le32_to_cpu(*dlct++); | ||
| 375 | |||
| 376 | /* add new devices, which are new in the LCT */ | ||
| 377 | list_for_each_entry_safe(dev, tmp, &c->devices, list) { | ||
| 378 | if (entry->tid == dev->lct_data.tid) { | ||
| 380 | found = 1; | 379 | found = 1; | 
| 381 | break; | 380 | break; | 
| 382 | } | 381 | } | 
| 383 | } | 382 | } | 
| 384 | 383 | ||
| 385 | if (!found) | 384 | if (!found) | 
| 386 | i2o_device_remove(dev); | 385 | i2o_device_add(c, entry); | 
| 386 | |||
| 387 | table_size -= 9; | ||
| 388 | max++; | ||
| 387 | } | 389 | } | 
| 388 | 390 | ||
| 389 | /* add new devices, which are new in the LCT */ | 391 | /* remove devices, which are not in the LCT anymore */ | 
| 390 | for (i = 0; i < max; i++) { | 392 | list_for_each_entry_safe(dev, tmp, &c->devices, list) { | 
| 391 | int found = 0; | 393 | int found = 0; | 
| 392 | 394 | ||
| 393 | list_for_each_entry_safe(dev, tmp, &c->devices, list) { | 395 | for (i = 0; i < max; i++) { | 
| 394 | if (lct->lct_entry[i].tid == dev->lct_data.tid) { | 396 | if (lct->lct_entry[i].tid == dev->lct_data.tid) { | 
| 395 | found = 1; | 397 | found = 1; | 
| 396 | break; | 398 | break; | 
| @@ -398,14 +400,14 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
| 398 | } | 400 | } | 
| 399 | 401 | ||
| 400 | if (!found) | 402 | if (!found) | 
| 401 | i2o_device_add(c, &lct->lct_entry[i]); | 403 | i2o_device_remove(dev); | 
| 402 | } | 404 | } | 
| 405 | |||
| 403 | up(&c->lct_lock); | 406 | up(&c->lct_lock); | 
| 404 | 407 | ||
| 405 | return 0; | 408 | return 0; | 
| 406 | } | 409 | } | 
| 407 | 410 | ||
| 408 | |||
| 409 | /* | 411 | /* | 
| 410 | * Run time support routines | 412 | * Run time support routines | 
| 411 | */ | 413 | */ | 
| @@ -419,13 +421,9 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
| 419 | * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. | 421 | * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. | 
| 420 | */ | 422 | */ | 
| 421 | int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | 423 | int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | 
| 422 | int oplen, void *reslist, int reslen) | 424 | int oplen, void *reslist, int reslen) | 
| 423 | { | 425 | { | 
| 424 | struct i2o_message __iomem *msg; | 426 | struct i2o_message *msg; | 
| 425 | u32 m; | ||
| 426 | u32 *res32 = (u32 *) reslist; | ||
| 427 | u32 *restmp = (u32 *) reslist; | ||
| 428 | int len = 0; | ||
| 429 | int i = 0; | 427 | int i = 0; | 
| 430 | int rc; | 428 | int rc; | 
| 431 | struct i2o_dma res; | 429 | struct i2o_dma res; | 
| @@ -437,26 +435,27 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | |||
| 437 | if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL)) | 435 | if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL)) | 
| 438 | return -ENOMEM; | 436 | return -ENOMEM; | 
| 439 | 437 | ||
| 440 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | 438 | msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); | 
| 441 | if (m == I2O_QUEUE_EMPTY) { | 439 | if (IS_ERR(msg)) { | 
| 442 | i2o_dma_free(dev, &res); | 440 | i2o_dma_free(dev, &res); | 
| 443 | return -ETIMEDOUT; | 441 | return PTR_ERR(msg); | 
| 444 | } | 442 | } | 
| 445 | 443 | ||
| 446 | i = 0; | 444 | i = 0; | 
| 447 | writel(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid, | 445 | msg->u.head[1] = | 
| 448 | &msg->u.head[1]); | 446 | cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid); | 
| 449 | writel(0, &msg->body[i++]); | 447 | msg->body[i++] = cpu_to_le32(0x00000000); | 
| 450 | writel(0x4C000000 | oplen, &msg->body[i++]); /* OperationList */ | 448 | msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */ | 
| 451 | memcpy_toio(&msg->body[i], oplist, oplen); | 449 | memcpy(&msg->body[i], oplist, oplen); | 
| 452 | i += (oplen / 4 + (oplen % 4 ? 1 : 0)); | 450 | i += (oplen / 4 + (oplen % 4 ? 1 : 0)); | 
| 453 | writel(0xD0000000 | res.len, &msg->body[i++]); /* ResultList */ | 451 | msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */ | 
| 454 | writel(res.phys, &msg->body[i++]); | 452 | msg->body[i++] = cpu_to_le32(res.phys); | 
| 455 | 453 | ||
| 456 | writel(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | | 454 | msg->u.head[0] = | 
| 457 | SGL_OFFSET_5, &msg->u.head[0]); | 455 | cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | | 
| 456 | SGL_OFFSET_5); | ||
| 458 | 457 | ||
| 459 | rc = i2o_msg_post_wait_mem(c, m, 10, &res); | 458 | rc = i2o_msg_post_wait_mem(c, msg, 10, &res); | 
| 460 | 459 | ||
| 461 | /* This only looks like a memory leak - don't "fix" it. */ | 460 | /* This only looks like a memory leak - don't "fix" it. */ | 
| 462 | if (rc == -ETIMEDOUT) | 461 | if (rc == -ETIMEDOUT) | 
| @@ -465,36 +464,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | |||
| 465 | memcpy(reslist, res.virt, res.len); | 464 | memcpy(reslist, res.virt, res.len); | 
| 466 | i2o_dma_free(dev, &res); | 465 | i2o_dma_free(dev, &res); | 
| 467 | 466 | ||
| 468 | /* Query failed */ | 467 | return rc; | 
| 469 | if (rc) | ||
| 470 | return rc; | ||
| 471 | /* | ||
| 472 | * Calculate number of bytes of Result LIST | ||
| 473 | * We need to loop through each Result BLOCK and grab the length | ||
| 474 | */ | ||
| 475 | restmp = res32 + 1; | ||
| 476 | len = 1; | ||
| 477 | for (i = 0; i < (res32[0] & 0X0000FFFF); i++) { | ||
| 478 | if (restmp[0] & 0x00FF0000) { /* BlockStatus != SUCCESS */ | ||
| 479 | printk(KERN_WARNING | ||
| 480 | "%s - Error:\n ErrorInfoSize = 0x%02x, " | ||
| 481 | "BlockStatus = 0x%02x, BlockSize = 0x%04x\n", | ||
| 482 | (cmd == | ||
| 483 | I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" : | ||
| 484 | "PARAMS_GET", res32[1] >> 24, | ||
| 485 | (res32[1] >> 16) & 0xFF, res32[1] & 0xFFFF); | ||
| 486 | |||
| 487 | /* | ||
| 488 | * If this is the only request,than we return an error | ||
| 489 | */ | ||
| 490 | if ((res32[0] & 0x0000FFFF) == 1) { | ||
| 491 | return -((res32[1] >> 16) & 0xFF); /* -BlockStatus */ | ||
| 492 | } | ||
| 493 | } | ||
| 494 | len += restmp[0] & 0x0000FFFF; /* Length of res BLOCK */ | ||
| 495 | restmp += restmp[0] & 0x0000FFFF; /* Skip to next BLOCK */ | ||
| 496 | } | ||
| 497 | return (len << 2); /* bytes used by result list */ | ||
| 498 | } | 468 | } | 
| 499 | 469 | ||
| 500 | /* | 470 | /* | 
| @@ -503,28 +473,25 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, | |||
| 503 | int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, | 473 | int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, | 
| 504 | void *buf, int buflen) | 474 | void *buf, int buflen) | 
| 505 | { | 475 | { | 
| 506 | u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; | 476 | u32 opblk[] = { cpu_to_le32(0x00000001), | 
| 477 | cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET), | ||
| 478 | cpu_to_le32((s16) field << 16 | 0x00000001) | ||
| 479 | }; | ||
| 507 | u8 *resblk; /* 8 bytes for header */ | 480 | u8 *resblk; /* 8 bytes for header */ | 
| 508 | int size; | 481 | int rc; | 
| 509 | |||
| 510 | if (field == -1) /* whole group */ | ||
| 511 | opblk[4] = -1; | ||
| 512 | 482 | ||
| 513 | resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC); | 483 | resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC); | 
| 514 | if (!resblk) | 484 | if (!resblk) | 
| 515 | return -ENOMEM; | 485 | return -ENOMEM; | 
| 516 | 486 | ||
| 517 | size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, | 487 | rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, | 
| 518 | sizeof(opblk), resblk, buflen + 8); | 488 | sizeof(opblk), resblk, buflen + 8); | 
| 519 | 489 | ||
| 520 | memcpy(buf, resblk + 8, buflen); /* cut off header */ | 490 | memcpy(buf, resblk + 8, buflen); /* cut off header */ | 
| 521 | 491 | ||
| 522 | kfree(resblk); | 492 | kfree(resblk); | 
| 523 | 493 | ||
| 524 | if (size > buflen) | 494 | return rc; | 
| 525 | return buflen; | ||
| 526 | |||
| 527 | return size; | ||
| 528 | } | 495 | } | 
| 529 | 496 | ||
| 530 | /* | 497 | /* | 
| @@ -534,12 +501,12 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, | |||
| 534 | * else return specific fields | 501 | * else return specific fields | 
| 535 | * ibuf contains fieldindexes | 502 | * ibuf contains fieldindexes | 
| 536 | * | 503 | * | 
| 537 | * if oper == I2O_PARAMS_LIST_GET, get from specific rows | 504 | * if oper == I2O_PARAMS_LIST_GET, get from specific rows | 
| 538 | * if fieldcount == -1 return all fields | 505 | * if fieldcount == -1 return all fields | 
| 539 | * ibuf contains rowcount, keyvalues | 506 | * ibuf contains rowcount, keyvalues | 
| 540 | * else return specific fields | 507 | * else return specific fields | 
| 541 | * fieldcount is # of fieldindexes | 508 | * fieldcount is # of fieldindexes | 
| 542 | * ibuf contains fieldindexes, rowcount, keyvalues | 509 | * ibuf contains fieldindexes, rowcount, keyvalues | 
| 543 | * | 510 | * | 
| 544 | * You could also use directly function i2o_issue_params(). | 511 | * You could also use directly function i2o_issue_params(). | 
| 545 | */ | 512 | */ | 
