aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-22 20:03:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-22 20:03:12 -0400
commit8abfc6e7a45eb74e51904bbae676fae008b11366 (patch)
tree57d0a24558c0693e3a52e8e756616f6c72def1e9 /drivers/block/cciss.c
parente9dd2b6837e26fe202708cce5ea4bb4ee3e3482e (diff)
parent6362beea8914cbd4630ccde3617d944aeca2d48f (diff)
Merge branch 'for-2.6.37/drivers' of git://git.kernel.dk/linux-2.6-block
* 'for-2.6.37/drivers' of git://git.kernel.dk/linux-2.6-block: (95 commits) cciss: fix PCI IDs for new Smart Array controllers drbd: add race-breaker to drbd_go_diskless drbd: use dynamic_dev_dbg to optionally log uuid changes dynamic_debug.h: Fix dynamic_dev_dbg() macro if CONFIG_DYNAMIC_DEBUG not set drbd: cleanup: change "<= 0" to "== 0" drbd: relax the grace period of the md_sync timer again drbd: add some more explicit drbd_md_sync drbd: drop wrong debug asserts, fix recently introduced race drbd: cleanup useless leftover warn/error printk's drbd: add explicit drbd_md_sync to drbd_resync_finished drbd: Do not log an ASSERT for P_OV_REQUEST packets while C_CONNECTED drbd: fix for possible deadlock on IO error during resync drbd: fix unlikely access after free and list corruption drbd: fix for spurious fullsync (uuids rotated too fast) drbd: allow for explicit resync-finished notifications drbd: preparation commit, using full state in receive_state() drbd: drbd_send_ack_dp must not rely on header information drbd: Fix regression in recv_bm_rle_bits (compressed bitmap) drbd: Fixed a stupid copy and paste error drbd: Allow larger values for c-fill-target. ... Fix up trivial conflict in drivers/block/ataflop.c due to BKL removal
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c864
1 files changed, 424 insertions, 440 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index c484c96e22a6..f09e6df15aa7 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -105,11 +105,12 @@ static const struct pci_device_id cciss_pci_device_id[] = {
105 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, 105 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249},
106 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A}, 106 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A},
107 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B}, 107 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B},
108 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3250}, 108 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3350},
109 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3251}, 109 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3351},
110 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3252}, 110 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3352},
111 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3253}, 111 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3353},
112 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3254}, 112 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354},
113 {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355},
113 {0,} 114 {0,}
114}; 115};
115 116
@@ -149,11 +150,12 @@ static struct board_type products[] = {
149 {0x3249103C, "Smart Array P812", &SA5_access}, 150 {0x3249103C, "Smart Array P812", &SA5_access},
150 {0x324A103C, "Smart Array P712m", &SA5_access}, 151 {0x324A103C, "Smart Array P712m", &SA5_access},
151 {0x324B103C, "Smart Array P711m", &SA5_access}, 152 {0x324B103C, "Smart Array P711m", &SA5_access},
152 {0x3250103C, "Smart Array", &SA5_access}, 153 {0x3350103C, "Smart Array", &SA5_access},
153 {0x3251103C, "Smart Array", &SA5_access}, 154 {0x3351103C, "Smart Array", &SA5_access},
154 {0x3252103C, "Smart Array", &SA5_access}, 155 {0x3352103C, "Smart Array", &SA5_access},
155 {0x3253103C, "Smart Array", &SA5_access}, 156 {0x3353103C, "Smart Array", &SA5_access},
156 {0x3254103C, "Smart Array", &SA5_access}, 157 {0x3354103C, "Smart Array", &SA5_access},
158 {0x3355103C, "Smart Array", &SA5_access},
157}; 159};
158 160
159/* How long to wait (in milliseconds) for board to go into simple mode */ 161/* How long to wait (in milliseconds) for board to go into simple mode */
@@ -1232,470 +1234,452 @@ static void check_ioctl_unit_attention(ctlr_info_t *h, CommandList_struct *c)
1232 c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) 1234 c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
1233 (void)check_for_unit_attention(h, c); 1235 (void)check_for_unit_attention(h, c);
1234} 1236}
1235/* 1237
1236 * ioctl 1238static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp)
1237 */
1238static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
1239 unsigned int cmd, unsigned long arg)
1240{ 1239{
1241 struct gendisk *disk = bdev->bd_disk; 1240 cciss_pci_info_struct pciinfo;
1242 ctlr_info_t *h = get_host(disk);
1243 drive_info_struct *drv = get_drv(disk);
1244 void __user *argp = (void __user *)arg;
1245 1241
1246 dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n", 1242 if (!argp)
1247 cmd, arg); 1243 return -EINVAL;
1248 switch (cmd) { 1244 pciinfo.domain = pci_domain_nr(h->pdev->bus);
1249 case CCISS_GETPCIINFO: 1245 pciinfo.bus = h->pdev->bus->number;
1250 { 1246 pciinfo.dev_fn = h->pdev->devfn;
1251 cciss_pci_info_struct pciinfo; 1247 pciinfo.board_id = h->board_id;
1252 1248 if (copy_to_user(argp, &pciinfo, sizeof(cciss_pci_info_struct)))
1253 if (!arg) 1249 return -EFAULT;
1254 return -EINVAL; 1250 return 0;
1255 pciinfo.domain = pci_domain_nr(h->pdev->bus); 1251}
1256 pciinfo.bus = h->pdev->bus->number;
1257 pciinfo.dev_fn = h->pdev->devfn;
1258 pciinfo.board_id = h->board_id;
1259 if (copy_to_user
1260 (argp, &pciinfo, sizeof(cciss_pci_info_struct)))
1261 return -EFAULT;
1262 return 0;
1263 }
1264 case CCISS_GETINTINFO:
1265 {
1266 cciss_coalint_struct intinfo;
1267 if (!arg)
1268 return -EINVAL;
1269 intinfo.delay =
1270 readl(&h->cfgtable->HostWrite.CoalIntDelay);
1271 intinfo.count =
1272 readl(&h->cfgtable->HostWrite.CoalIntCount);
1273 if (copy_to_user
1274 (argp, &intinfo, sizeof(cciss_coalint_struct)))
1275 return -EFAULT;
1276 return 0;
1277 }
1278 case CCISS_SETINTINFO:
1279 {
1280 cciss_coalint_struct intinfo;
1281 unsigned long flags;
1282 int i;
1283
1284 if (!arg)
1285 return -EINVAL;
1286 if (!capable(CAP_SYS_ADMIN))
1287 return -EPERM;
1288 if (copy_from_user
1289 (&intinfo, argp, sizeof(cciss_coalint_struct)))
1290 return -EFAULT;
1291 if ((intinfo.delay == 0) && (intinfo.count == 0))
1292 return -EINVAL;
1293 spin_lock_irqsave(&h->lock, flags);
1294 /* Update the field, and then ring the doorbell */
1295 writel(intinfo.delay,
1296 &(h->cfgtable->HostWrite.CoalIntDelay));
1297 writel(intinfo.count,
1298 &(h->cfgtable->HostWrite.CoalIntCount));
1299 writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
1300
1301 for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
1302 if (!(readl(h->vaddr + SA5_DOORBELL)
1303 & CFGTBL_ChangeReq))
1304 break;
1305 /* delay and try again */
1306 udelay(1000);
1307 }
1308 spin_unlock_irqrestore(&h->lock, flags);
1309 if (i >= MAX_IOCTL_CONFIG_WAIT)
1310 return -EAGAIN;
1311 return 0;
1312 }
1313 case CCISS_GETNODENAME:
1314 {
1315 NodeName_type NodeName;
1316 int i;
1317
1318 if (!arg)
1319 return -EINVAL;
1320 for (i = 0; i < 16; i++)
1321 NodeName[i] =
1322 readb(&h->cfgtable->ServerName[i]);
1323 if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
1324 return -EFAULT;
1325 return 0;
1326 }
1327 case CCISS_SETNODENAME:
1328 {
1329 NodeName_type NodeName;
1330 unsigned long flags;
1331 int i;
1332 1252
1333 if (!arg) 1253static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
1334 return -EINVAL; 1254{
1335 if (!capable(CAP_SYS_ADMIN)) 1255 cciss_coalint_struct intinfo;
1336 return -EPERM;
1337 1256
1338 if (copy_from_user 1257 if (!argp)
1339 (NodeName, argp, sizeof(NodeName_type))) 1258 return -EINVAL;
1340 return -EFAULT; 1259 intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay);
1260 intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount);
1261 if (copy_to_user
1262 (argp, &intinfo, sizeof(cciss_coalint_struct)))
1263 return -EFAULT;
1264 return 0;
1265}
1341 1266
1342 spin_lock_irqsave(&h->lock, flags); 1267static int cciss_setintinfo(ctlr_info_t *h, void __user *argp)
1268{
1269 cciss_coalint_struct intinfo;
1270 unsigned long flags;
1271 int i;
1343 1272
1344 /* Update the field, and then ring the doorbell */ 1273 if (!argp)
1345 for (i = 0; i < 16; i++) 1274 return -EINVAL;
1346 writeb(NodeName[i], 1275 if (!capable(CAP_SYS_ADMIN))
1347 &h->cfgtable->ServerName[i]); 1276 return -EPERM;
1277 if (copy_from_user(&intinfo, argp, sizeof(intinfo)))
1278 return -EFAULT;
1279 if ((intinfo.delay == 0) && (intinfo.count == 0))
1280 return -EINVAL;
1281 spin_lock_irqsave(&h->lock, flags);
1282 /* Update the field, and then ring the doorbell */
1283 writel(intinfo.delay, &(h->cfgtable->HostWrite.CoalIntDelay));
1284 writel(intinfo.count, &(h->cfgtable->HostWrite.CoalIntCount));
1285 writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
1348 1286
1349 writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); 1287 for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
1288 if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
1289 break;
1290 udelay(1000); /* delay and try again */
1291 }
1292 spin_unlock_irqrestore(&h->lock, flags);
1293 if (i >= MAX_IOCTL_CONFIG_WAIT)
1294 return -EAGAIN;
1295 return 0;
1296}
1350 1297
1351 for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) { 1298static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
1352 if (!(readl(h->vaddr + SA5_DOORBELL) 1299{
1353 & CFGTBL_ChangeReq)) 1300 NodeName_type NodeName;
1354 break; 1301 int i;
1355 /* delay and try again */
1356 udelay(1000);
1357 }
1358 spin_unlock_irqrestore(&h->lock, flags);
1359 if (i >= MAX_IOCTL_CONFIG_WAIT)
1360 return -EAGAIN;
1361 return 0;
1362 }
1363 1302
1364 case CCISS_GETHEARTBEAT: 1303 if (!argp)
1365 { 1304 return -EINVAL;
1366 Heartbeat_type heartbeat; 1305 for (i = 0; i < 16; i++)
1367 1306 NodeName[i] = readb(&h->cfgtable->ServerName[i]);
1368 if (!arg) 1307 if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
1369 return -EINVAL; 1308 return -EFAULT;
1370 heartbeat = readl(&h->cfgtable->HeartBeat); 1309 return 0;
1371 if (copy_to_user 1310}
1372 (argp, &heartbeat, sizeof(Heartbeat_type)))
1373 return -EFAULT;
1374 return 0;
1375 }
1376 case CCISS_GETBUSTYPES:
1377 {
1378 BusTypes_type BusTypes;
1379
1380 if (!arg)
1381 return -EINVAL;
1382 BusTypes = readl(&h->cfgtable->BusTypes);
1383 if (copy_to_user
1384 (argp, &BusTypes, sizeof(BusTypes_type)))
1385 return -EFAULT;
1386 return 0;
1387 }
1388 case CCISS_GETFIRMVER:
1389 {
1390 FirmwareVer_type firmware;
1391 1311
1392 if (!arg) 1312static int cciss_setnodename(ctlr_info_t *h, void __user *argp)
1393 return -EINVAL; 1313{
1394 memcpy(firmware, h->firm_ver, 4); 1314 NodeName_type NodeName;
1315 unsigned long flags;
1316 int i;
1395 1317
1396 if (copy_to_user 1318 if (!argp)
1397 (argp, firmware, sizeof(FirmwareVer_type))) 1319 return -EINVAL;
1398 return -EFAULT; 1320 if (!capable(CAP_SYS_ADMIN))
1399 return 0; 1321 return -EPERM;
1400 } 1322 if (copy_from_user(NodeName, argp, sizeof(NodeName_type)))
1401 case CCISS_GETDRIVVER: 1323 return -EFAULT;
1402 { 1324 spin_lock_irqsave(&h->lock, flags);
1403 DriverVer_type DriverVer = DRIVER_VERSION; 1325 /* Update the field, and then ring the doorbell */
1326 for (i = 0; i < 16; i++)
1327 writeb(NodeName[i], &h->cfgtable->ServerName[i]);
1328 writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
1329 for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
1330 if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
1331 break;
1332 udelay(1000); /* delay and try again */
1333 }
1334 spin_unlock_irqrestore(&h->lock, flags);
1335 if (i >= MAX_IOCTL_CONFIG_WAIT)
1336 return -EAGAIN;
1337 return 0;
1338}
1404 1339
1405 if (!arg) 1340static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
1406 return -EINVAL; 1341{
1342 Heartbeat_type heartbeat;
1407 1343
1408 if (copy_to_user 1344 if (!argp)
1409 (argp, &DriverVer, sizeof(DriverVer_type))) 1345 return -EINVAL;
1410 return -EFAULT; 1346 heartbeat = readl(&h->cfgtable->HeartBeat);
1411 return 0; 1347 if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type)))
1412 } 1348 return -EFAULT;
1349 return 0;
1350}
1413 1351
1414 case CCISS_DEREGDISK: 1352static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
1415 case CCISS_REGNEWD: 1353{
1416 case CCISS_REVALIDVOLS: 1354 BusTypes_type BusTypes;
1417 return rebuild_lun_table(h, 0, 1); 1355
1356 if (!argp)
1357 return -EINVAL;
1358 BusTypes = readl(&h->cfgtable->BusTypes);
1359 if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type)))
1360 return -EFAULT;
1361 return 0;
1362}
1418 1363
1419 case CCISS_GETLUNINFO:{ 1364static int cciss_getfirmver(ctlr_info_t *h, void __user *argp)
1420 LogvolInfo_struct luninfo; 1365{
1366 FirmwareVer_type firmware;
1421 1367
1422 memcpy(&luninfo.LunID, drv->LunID, 1368 if (!argp)
1423 sizeof(luninfo.LunID)); 1369 return -EINVAL;
1424 luninfo.num_opens = drv->usage_count; 1370 memcpy(firmware, h->firm_ver, 4);
1425 luninfo.num_parts = 0; 1371
1426 if (copy_to_user(argp, &luninfo, 1372 if (copy_to_user
1427 sizeof(LogvolInfo_struct))) 1373 (argp, firmware, sizeof(FirmwareVer_type)))
1428 return -EFAULT; 1374 return -EFAULT;
1429 return 0; 1375 return 0;
1376}
1377
1378static int cciss_getdrivver(ctlr_info_t *h, void __user *argp)
1379{
1380 DriverVer_type DriverVer = DRIVER_VERSION;
1381
1382 if (!argp)
1383 return -EINVAL;
1384 if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type)))
1385 return -EFAULT;
1386 return 0;
1387}
1388
1389static int cciss_getluninfo(ctlr_info_t *h,
1390 struct gendisk *disk, void __user *argp)
1391{
1392 LogvolInfo_struct luninfo;
1393 drive_info_struct *drv = get_drv(disk);
1394
1395 if (!argp)
1396 return -EINVAL;
1397 memcpy(&luninfo.LunID, drv->LunID, sizeof(luninfo.LunID));
1398 luninfo.num_opens = drv->usage_count;
1399 luninfo.num_parts = 0;
1400 if (copy_to_user(argp, &luninfo, sizeof(LogvolInfo_struct)))
1401 return -EFAULT;
1402 return 0;
1403}
1404
1405static int cciss_passthru(ctlr_info_t *h, void __user *argp)
1406{
1407 IOCTL_Command_struct iocommand;
1408 CommandList_struct *c;
1409 char *buff = NULL;
1410 u64bit temp64;
1411 DECLARE_COMPLETION_ONSTACK(wait);
1412
1413 if (!argp)
1414 return -EINVAL;
1415
1416 if (!capable(CAP_SYS_RAWIO))
1417 return -EPERM;
1418
1419 if (copy_from_user
1420 (&iocommand, argp, sizeof(IOCTL_Command_struct)))
1421 return -EFAULT;
1422 if ((iocommand.buf_size < 1) &&
1423 (iocommand.Request.Type.Direction != XFER_NONE)) {
1424 return -EINVAL;
1425 }
1426 if (iocommand.buf_size > 0) {
1427 buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
1428 if (buff == NULL)
1429 return -EFAULT;
1430 }
1431 if (iocommand.Request.Type.Direction == XFER_WRITE) {
1432 /* Copy the data into the buffer we created */
1433 if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
1434 kfree(buff);
1435 return -EFAULT;
1430 } 1436 }
1431 case CCISS_PASSTHRU: 1437 } else {
1432 { 1438 memset(buff, 0, iocommand.buf_size);
1433 IOCTL_Command_struct iocommand; 1439 }
1434 CommandList_struct *c; 1440 c = cmd_special_alloc(h);
1435 char *buff = NULL; 1441 if (!c) {
1436 u64bit temp64; 1442 kfree(buff);
1437 DECLARE_COMPLETION_ONSTACK(wait); 1443 return -ENOMEM;
1438 1444 }
1439 if (!arg) 1445 /* Fill in the command type */
1440 return -EINVAL; 1446 c->cmd_type = CMD_IOCTL_PEND;
1441 1447 /* Fill in Command Header */
1442 if (!capable(CAP_SYS_RAWIO)) 1448 c->Header.ReplyQueue = 0; /* unused in simple mode */
1443 return -EPERM; 1449 if (iocommand.buf_size > 0) { /* buffer to fill */
1444 1450 c->Header.SGList = 1;
1445 if (copy_from_user 1451 c->Header.SGTotal = 1;
1446 (&iocommand, argp, sizeof(IOCTL_Command_struct))) 1452 } else { /* no buffers to fill */
1447 return -EFAULT; 1453 c->Header.SGList = 0;
1448 if ((iocommand.buf_size < 1) && 1454 c->Header.SGTotal = 0;
1449 (iocommand.Request.Type.Direction != XFER_NONE)) { 1455 }
1450 return -EINVAL; 1456 c->Header.LUN = iocommand.LUN_info;
1451 } 1457 /* use the kernel address the cmd block for tag */
1452#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */ 1458 c->Header.Tag.lower = c->busaddr;
1453 /* Check kmalloc limits */
1454 if (iocommand.buf_size > 128000)
1455 return -EINVAL;
1456#endif
1457 if (iocommand.buf_size > 0) {
1458 buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
1459 if (buff == NULL)
1460 return -EFAULT;
1461 }
1462 if (iocommand.Request.Type.Direction == XFER_WRITE) {
1463 /* Copy the data into the buffer we created */
1464 if (copy_from_user
1465 (buff, iocommand.buf, iocommand.buf_size)) {
1466 kfree(buff);
1467 return -EFAULT;
1468 }
1469 } else {
1470 memset(buff, 0, iocommand.buf_size);
1471 }
1472 c = cmd_special_alloc(h);
1473 if (!c) {
1474 kfree(buff);
1475 return -ENOMEM;
1476 }
1477 /* Fill in the command type */
1478 c->cmd_type = CMD_IOCTL_PEND;
1479 /* Fill in Command Header */
1480 c->Header.ReplyQueue = 0; /* unused in simple mode */
1481 if (iocommand.buf_size > 0) /* buffer to fill */
1482 {
1483 c->Header.SGList = 1;
1484 c->Header.SGTotal = 1;
1485 } else /* no buffers to fill */
1486 {
1487 c->Header.SGList = 0;
1488 c->Header.SGTotal = 0;
1489 }
1490 c->Header.LUN = iocommand.LUN_info;
1491 /* use the kernel address the cmd block for tag */
1492 c->Header.Tag.lower = c->busaddr;
1493
1494 /* Fill in Request block */
1495 c->Request = iocommand.Request;
1496
1497 /* Fill in the scatter gather information */
1498 if (iocommand.buf_size > 0) {
1499 temp64.val = pci_map_single(h->pdev, buff,
1500 iocommand.buf_size,
1501 PCI_DMA_BIDIRECTIONAL);
1502 c->SG[0].Addr.lower = temp64.val32.lower;
1503 c->SG[0].Addr.upper = temp64.val32.upper;
1504 c->SG[0].Len = iocommand.buf_size;
1505 c->SG[0].Ext = 0; /* we are not chaining */
1506 }
1507 c->waiting = &wait;
1508 1459
1509 enqueue_cmd_and_start_io(h, c); 1460 /* Fill in Request block */
1510 wait_for_completion(&wait); 1461 c->Request = iocommand.Request;
1511 1462
1512 /* unlock the buffers from DMA */ 1463 /* Fill in the scatter gather information */
1513 temp64.val32.lower = c->SG[0].Addr.lower; 1464 if (iocommand.buf_size > 0) {
1514 temp64.val32.upper = c->SG[0].Addr.upper; 1465 temp64.val = pci_map_single(h->pdev, buff,
1515 pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, 1466 iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
1516 iocommand.buf_size, 1467 c->SG[0].Addr.lower = temp64.val32.lower;
1517 PCI_DMA_BIDIRECTIONAL); 1468 c->SG[0].Addr.upper = temp64.val32.upper;
1469 c->SG[0].Len = iocommand.buf_size;
1470 c->SG[0].Ext = 0; /* we are not chaining */
1471 }
1472 c->waiting = &wait;
1518 1473
1519 check_ioctl_unit_attention(h, c); 1474 enqueue_cmd_and_start_io(h, c);
1475 wait_for_completion(&wait);
1520 1476
1521 /* Copy the error information out */ 1477 /* unlock the buffers from DMA */
1522 iocommand.error_info = *(c->err_info); 1478 temp64.val32.lower = c->SG[0].Addr.lower;
1523 if (copy_to_user 1479 temp64.val32.upper = c->SG[0].Addr.upper;
1524 (argp, &iocommand, sizeof(IOCTL_Command_struct))) { 1480 pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, iocommand.buf_size,
1525 kfree(buff); 1481 PCI_DMA_BIDIRECTIONAL);
1526 cmd_special_free(h, c); 1482 check_ioctl_unit_attention(h, c);
1527 return -EFAULT; 1483
1528 } 1484 /* Copy the error information out */
1485 iocommand.error_info = *(c->err_info);
1486 if (copy_to_user(argp, &iocommand, sizeof(IOCTL_Command_struct))) {
1487 kfree(buff);
1488 cmd_special_free(h, c);
1489 return -EFAULT;
1490 }
1529 1491
1530 if (iocommand.Request.Type.Direction == XFER_READ) { 1492 if (iocommand.Request.Type.Direction == XFER_READ) {
1531 /* Copy the data out of the buffer we created */ 1493 /* Copy the data out of the buffer we created */
1532 if (copy_to_user 1494 if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
1533 (iocommand.buf, buff, iocommand.buf_size)) {
1534 kfree(buff);
1535 cmd_special_free(h, c);
1536 return -EFAULT;
1537 }
1538 }
1539 kfree(buff); 1495 kfree(buff);
1540 cmd_special_free(h, c); 1496 cmd_special_free(h, c);
1541 return 0; 1497 return -EFAULT;
1542 } 1498 }
1543 case CCISS_BIG_PASSTHRU:{ 1499 }
1544 BIG_IOCTL_Command_struct *ioc; 1500 kfree(buff);
1545 CommandList_struct *c; 1501 cmd_special_free(h, c);
1546 unsigned char **buff = NULL; 1502 return 0;
1547 int *buff_size = NULL; 1503}
1548 u64bit temp64; 1504
1549 BYTE sg_used = 0; 1505static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp)
1550 int status = 0; 1506{
1551 int i; 1507 BIG_IOCTL_Command_struct *ioc;
1552 DECLARE_COMPLETION_ONSTACK(wait); 1508 CommandList_struct *c;
1553 __u32 left; 1509 unsigned char **buff = NULL;
1554 __u32 sz; 1510 int *buff_size = NULL;
1555 BYTE __user *data_ptr; 1511 u64bit temp64;
1556 1512 BYTE sg_used = 0;
1557 if (!arg) 1513 int status = 0;
1558 return -EINVAL; 1514 int i;
1559 if (!capable(CAP_SYS_RAWIO)) 1515 DECLARE_COMPLETION_ONSTACK(wait);
1560 return -EPERM; 1516 __u32 left;
1561 ioc = (BIG_IOCTL_Command_struct *) 1517 __u32 sz;
1562 kmalloc(sizeof(*ioc), GFP_KERNEL); 1518 BYTE __user *data_ptr;
1563 if (!ioc) { 1519
1564 status = -ENOMEM; 1520 if (!argp)
1565 goto cleanup1; 1521 return -EINVAL;
1566 } 1522 if (!capable(CAP_SYS_RAWIO))
1567 if (copy_from_user(ioc, argp, sizeof(*ioc))) { 1523 return -EPERM;
1524 ioc = (BIG_IOCTL_Command_struct *)
1525 kmalloc(sizeof(*ioc), GFP_KERNEL);
1526 if (!ioc) {
1527 status = -ENOMEM;
1528 goto cleanup1;
1529 }
1530 if (copy_from_user(ioc, argp, sizeof(*ioc))) {
1531 status = -EFAULT;
1532 goto cleanup1;
1533 }
1534 if ((ioc->buf_size < 1) &&
1535 (ioc->Request.Type.Direction != XFER_NONE)) {
1536 status = -EINVAL;
1537 goto cleanup1;
1538 }
1539 /* Check kmalloc limits using all SGs */
1540 if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
1541 status = -EINVAL;
1542 goto cleanup1;
1543 }
1544 if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
1545 status = -EINVAL;
1546 goto cleanup1;
1547 }
1548 buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
1549 if (!buff) {
1550 status = -ENOMEM;
1551 goto cleanup1;
1552 }
1553 buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL);
1554 if (!buff_size) {
1555 status = -ENOMEM;
1556 goto cleanup1;
1557 }
1558 left = ioc->buf_size;
1559 data_ptr = ioc->buf;
1560 while (left) {
1561 sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
1562 buff_size[sg_used] = sz;
1563 buff[sg_used] = kmalloc(sz, GFP_KERNEL);
1564 if (buff[sg_used] == NULL) {
1565 status = -ENOMEM;
1566 goto cleanup1;
1567 }
1568 if (ioc->Request.Type.Direction == XFER_WRITE) {
1569 if (copy_from_user(buff[sg_used], data_ptr, sz)) {
1568 status = -EFAULT; 1570 status = -EFAULT;
1569 goto cleanup1; 1571 goto cleanup1;
1570 } 1572 }
1571 if ((ioc->buf_size < 1) && 1573 } else {
1572 (ioc->Request.Type.Direction != XFER_NONE)) { 1574 memset(buff[sg_used], 0, sz);
1573 status = -EINVAL; 1575 }
1574 goto cleanup1; 1576 left -= sz;
1575 } 1577 data_ptr += sz;
1576 /* Check kmalloc limits using all SGs */ 1578 sg_used++;
1577 if (ioc->malloc_size > MAX_KMALLOC_SIZE) { 1579 }
1578 status = -EINVAL; 1580 c = cmd_special_alloc(h);
1579 goto cleanup1; 1581 if (!c) {
1580 } 1582 status = -ENOMEM;
1581 if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) { 1583 goto cleanup1;
1582 status = -EINVAL; 1584 }
1583 goto cleanup1; 1585 c->cmd_type = CMD_IOCTL_PEND;
1584 } 1586 c->Header.ReplyQueue = 0;
1585 buff = 1587 c->Header.SGList = sg_used;
1586 kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL); 1588 c->Header.SGTotal = sg_used;
1587 if (!buff) { 1589 c->Header.LUN = ioc->LUN_info;
1588 status = -ENOMEM; 1590 c->Header.Tag.lower = c->busaddr;
1589 goto cleanup1;
1590 }
1591 buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
1592 GFP_KERNEL);
1593 if (!buff_size) {
1594 status = -ENOMEM;
1595 goto cleanup1;
1596 }
1597 left = ioc->buf_size;
1598 data_ptr = ioc->buf;
1599 while (left) {
1600 sz = (left >
1601 ioc->malloc_size) ? ioc->
1602 malloc_size : left;
1603 buff_size[sg_used] = sz;
1604 buff[sg_used] = kmalloc(sz, GFP_KERNEL);
1605 if (buff[sg_used] == NULL) {
1606 status = -ENOMEM;
1607 goto cleanup1;
1608 }
1609 if (ioc->Request.Type.Direction == XFER_WRITE) {
1610 if (copy_from_user
1611 (buff[sg_used], data_ptr, sz)) {
1612 status = -EFAULT;
1613 goto cleanup1;
1614 }
1615 } else {
1616 memset(buff[sg_used], 0, sz);
1617 }
1618 left -= sz;
1619 data_ptr += sz;
1620 sg_used++;
1621 }
1622 c = cmd_special_alloc(h);
1623 if (!c) {
1624 status = -ENOMEM;
1625 goto cleanup1;
1626 }
1627 c->cmd_type = CMD_IOCTL_PEND;
1628 c->Header.ReplyQueue = 0;
1629 1591
1630 if (ioc->buf_size > 0) { 1592 c->Request = ioc->Request;
1631 c->Header.SGList = sg_used; 1593 for (i = 0; i < sg_used; i++) {
1632 c->Header.SGTotal = sg_used; 1594 temp64.val = pci_map_single(h->pdev, buff[i], buff_size[i],
1633 } else { 1595 PCI_DMA_BIDIRECTIONAL);
1634 c->Header.SGList = 0; 1596 c->SG[i].Addr.lower = temp64.val32.lower;
1635 c->Header.SGTotal = 0; 1597 c->SG[i].Addr.upper = temp64.val32.upper;
1636 } 1598 c->SG[i].Len = buff_size[i];
1637 c->Header.LUN = ioc->LUN_info; 1599 c->SG[i].Ext = 0; /* we are not chaining */
1638 c->Header.Tag.lower = c->busaddr; 1600 }
1639 1601 c->waiting = &wait;
1640 c->Request = ioc->Request; 1602 enqueue_cmd_and_start_io(h, c);
1641 if (ioc->buf_size > 0) { 1603 wait_for_completion(&wait);
1642 for (i = 0; i < sg_used; i++) { 1604 /* unlock the buffers from DMA */
1643 temp64.val = 1605 for (i = 0; i < sg_used; i++) {
1644 pci_map_single(h->pdev, buff[i], 1606 temp64.val32.lower = c->SG[i].Addr.lower;
1645 buff_size[i], 1607 temp64.val32.upper = c->SG[i].Addr.upper;
1646 PCI_DMA_BIDIRECTIONAL); 1608 pci_unmap_single(h->pdev,
1647 c->SG[i].Addr.lower = 1609 (dma_addr_t) temp64.val, buff_size[i],
1648 temp64.val32.lower; 1610 PCI_DMA_BIDIRECTIONAL);
1649 c->SG[i].Addr.upper = 1611 }
1650 temp64.val32.upper; 1612 check_ioctl_unit_attention(h, c);
1651 c->SG[i].Len = buff_size[i]; 1613 /* Copy the error information out */
1652 c->SG[i].Ext = 0; /* we are not chaining */ 1614 ioc->error_info = *(c->err_info);
1653 } 1615 if (copy_to_user(argp, ioc, sizeof(*ioc))) {
1654 } 1616 cmd_special_free(h, c);
1655 c->waiting = &wait; 1617 status = -EFAULT;
1656 enqueue_cmd_and_start_io(h, c); 1618 goto cleanup1;
1657 wait_for_completion(&wait); 1619 }
1658 /* unlock the buffers from DMA */ 1620 if (ioc->Request.Type.Direction == XFER_READ) {
1659 for (i = 0; i < sg_used; i++) { 1621 /* Copy the data out of the buffer we created */
1660 temp64.val32.lower = c->SG[i].Addr.lower; 1622 BYTE __user *ptr = ioc->buf;
1661 temp64.val32.upper = c->SG[i].Addr.upper; 1623 for (i = 0; i < sg_used; i++) {
1662 pci_unmap_single(h->pdev, 1624 if (copy_to_user(ptr, buff[i], buff_size[i])) {
1663 (dma_addr_t) temp64.val, buff_size[i],
1664 PCI_DMA_BIDIRECTIONAL);
1665 }
1666 check_ioctl_unit_attention(h, c);
1667 /* Copy the error information out */
1668 ioc->error_info = *(c->err_info);
1669 if (copy_to_user(argp, ioc, sizeof(*ioc))) {
1670 cmd_special_free(h, c); 1625 cmd_special_free(h, c);
1671 status = -EFAULT; 1626 status = -EFAULT;
1672 goto cleanup1; 1627 goto cleanup1;
1673 } 1628 }
1674 if (ioc->Request.Type.Direction == XFER_READ) { 1629 ptr += buff_size[i];
1675 /* Copy the data out of the buffer we created */
1676 BYTE __user *ptr = ioc->buf;
1677 for (i = 0; i < sg_used; i++) {
1678 if (copy_to_user
1679 (ptr, buff[i], buff_size[i])) {
1680 cmd_special_free(h, c);
1681 status = -EFAULT;
1682 goto cleanup1;
1683 }
1684 ptr += buff_size[i];
1685 }
1686 }
1687 cmd_special_free(h, c);
1688 status = 0;
1689 cleanup1:
1690 if (buff) {
1691 for (i = 0; i < sg_used; i++)
1692 kfree(buff[i]);
1693 kfree(buff);
1694 }
1695 kfree(buff_size);
1696 kfree(ioc);
1697 return status;
1698 } 1630 }
1631 }
1632 cmd_special_free(h, c);
1633 status = 0;
1634cleanup1:
1635 if (buff) {
1636 for (i = 0; i < sg_used; i++)
1637 kfree(buff[i]);
1638 kfree(buff);
1639 }
1640 kfree(buff_size);
1641 kfree(ioc);
1642 return status;
1643}
1644
1645static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
1646 unsigned int cmd, unsigned long arg)
1647{
1648 struct gendisk *disk = bdev->bd_disk;
1649 ctlr_info_t *h = get_host(disk);
1650 void __user *argp = (void __user *)arg;
1651
1652 dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n",
1653 cmd, arg);
1654 switch (cmd) {
1655 case CCISS_GETPCIINFO:
1656 return cciss_getpciinfo(h, argp);
1657 case CCISS_GETINTINFO:
1658 return cciss_getintinfo(h, argp);
1659 case CCISS_SETINTINFO:
1660 return cciss_setintinfo(h, argp);
1661 case CCISS_GETNODENAME:
1662 return cciss_getnodename(h, argp);
1663 case CCISS_SETNODENAME:
1664 return cciss_setnodename(h, argp);
1665 case CCISS_GETHEARTBEAT:
1666 return cciss_getheartbeat(h, argp);
1667 case CCISS_GETBUSTYPES:
1668 return cciss_getbustypes(h, argp);
1669 case CCISS_GETFIRMVER:
1670 return cciss_getfirmver(h, argp);
1671 case CCISS_GETDRIVVER:
1672 return cciss_getdrivver(h, argp);
1673 case CCISS_DEREGDISK:
1674 case CCISS_REGNEWD:
1675 case CCISS_REVALIDVOLS:
1676 return rebuild_lun_table(h, 0, 1);
1677 case CCISS_GETLUNINFO:
1678 return cciss_getluninfo(h, disk, argp);
1679 case CCISS_PASSTHRU:
1680 return cciss_passthru(h, argp);
1681 case CCISS_BIG_PASSTHRU:
1682 return cciss_bigpassthru(h, argp);
1699 1683
1700 /* scsi_cmd_ioctl handles these, below, though some are not */ 1684 /* scsi_cmd_ioctl handles these, below, though some are not */
1701 /* very meaningful for cciss. SG_IO is the main one people want. */ 1685 /* very meaningful for cciss. SG_IO is the main one people want. */